﻿using System;
using Ant.Interface.Data.Migration.Interpreters;
using Ant.Interface.Data.Migration.Schema;

namespace Ant.BasicPlugIn.Data.Migration.Schema
{
    public class SchemaBuilder : ISchemaBuilder
    {
        private readonly IDataMigrationInterpreter _interpreter;

        private readonly string _featurePrefix = string.Empty;
        private readonly Func<string, string> _formatPrefix = s => s ?? string.Empty;

        //[ImportingConstructor]
        //public SchemaBuilder(IDataMigrationInterpreter interpreter)
        //    : this(interpreter, null, null)
        //{ }

        //public SchemaBuilder(IDataMigrationInterpreter interpreter, string featurePrefix, Func<string, string> formatPrefix)
        //{
        //    _interpreter = interpreter;
        //    _featurePrefix = featurePrefix ?? String.Empty;
        //    _formatPrefix = formatPrefix ?? (s => s ?? String.Empty);
        //}

        public ISchemaBuilder CreateTable(string name, Action<CreateTableCommand> table)
        {
            var createTable = new CreateTableCommand(String.Concat(_formatPrefix(_featurePrefix), name));
            table(createTable);
            Run(createTable);
            return this;
        }

        public ISchemaBuilder AlterTable(string name, Action<AlterTableCommand> table)
        {
            var alterTable = new AlterTableCommand(String.Concat(_formatPrefix(_featurePrefix), name));
            table(alterTable);
            Run(alterTable);
            return this;
        }

        public ISchemaBuilder DropTable(string name)
        {
            var deleteTable = new DropTableCommand(String.Concat(_formatPrefix(_featurePrefix), name));
            Run(deleteTable);
            return this;
        }

        public ISchemaBuilder ExecuteSql(string sql, Action<SqlStatementCommand> statement = null)
        {
            var sqlStatmentCommand = new SqlStatementCommand(sql);
            if (statement != null)
            {
                statement(sqlStatmentCommand);
            }
            Run(sqlStatmentCommand);
            return this;
        }

        private void Run(ISchemaBuilderCommand command)
        {
            _interpreter.Visit(command);
        }

        public ISchemaBuilder CreateForeignKey(string name, string srcTable, string[] srcColumns, string destTable, string[] destColumns)
        {
            var command = new CreateForeignKeyCommand(name, String.Concat(_formatPrefix(_featurePrefix), srcTable), srcColumns, String.Concat(_formatPrefix(_featurePrefix), destTable), destColumns);
            Run(command);
            return this;
        }

        public ISchemaBuilder CreateForeignKey(string name, string srcModule, string srcTable, string[] srcColumns, string destTable, string[] destColumns)
        {
            var command = new CreateForeignKeyCommand(name, String.Concat(_formatPrefix(srcModule), srcTable), srcColumns, String.Concat(_formatPrefix(_featurePrefix), destTable), destColumns);
            Run(command);
            return this;
        }

        public ISchemaBuilder CreateForeignKey(string name, string srcTable, string[] srcColumns, string destModule, string destTable, string[] destColumns)
        {
            var command = new CreateForeignKeyCommand(name, String.Concat(_formatPrefix(_featurePrefix), srcTable), srcColumns, String.Concat(_formatPrefix(destModule), destTable), destColumns);
            Run(command);
            return this;
        }

        public ISchemaBuilder CreateForeignKey(string name, string srcModule, string srcTable, string[] srcColumns, string destModule, string destTable, string[] destColumns)
        {
            var command = new CreateForeignKeyCommand(name, String.Concat(_formatPrefix(srcModule), srcTable), srcColumns, String.Concat(_formatPrefix(destModule), destTable), destColumns);
            Run(command);
            return this;
        }

        public ISchemaBuilder DropForeignKey(string srcTable, string name)
        {
            var command = new DropForeignKeyCommand(String.Concat(_formatPrefix(_featurePrefix), srcTable), name);
            Run(command);
            return this;
        }

        public ISchemaBuilder DropForeignKey(string srcModule, string srcTable, string name)
        {
            var command = new DropForeignKeyCommand(String.Concat(_formatPrefix(srcModule), srcTable), name);
            Run(command);
            return this;
        }
    }
}